package com.plugin.uniapp.dialog;

import android.animation.ObjectAnimator;
import android.app.Dialog;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import com.plugin.uniapp.Config;
import com.plugin.uniapp.MainActivity;
import com.plugin.uniapp.R;
import com.plugin.uniapp.Task;
import com.plugin.uniapp.utils.AnimType;
import com.plugin.uniapp.utils.HttpHelper;
import com.plugin.uniapp.utils.Logger;
import com.plugin.uniapp.utils.WebSocketClient;
import com.plugin.uniapp.video.SurfacePlayer;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MultiViewDialog extends Dialog {
    public interface ReqTasks {
        void callback(Map<Integer, String> tasks);
    }

    public interface WebSocketMsg {
        void onRes(JSONObject data, boolean isTimeout);
    }

    public static MultiViewDialog instance;
    public static Handler handler = new Handler(Looper.getMainLooper());
    public String currDeviceId;
    public String currView;
    public VideoView videoView;
    public AccountView accountView;
    public CaptchaView captchaView;
    public TasksView tasksView;
    public WebSocketClient msgClientSocket;
    public List<Task> taskList = new ArrayList<>();
    private JSONArray alltask;
    public int currTaskIndex;
    public boolean currTaskComplated;
    public Map<String, WebSocketMsg> webSocketEvents = new HashMap<>();
    private final MainActivity activity;
    public TextView txtLogger;
    public ImageView titleRightIcon;
    public ObjectAnimator titleRightIconAnim;
    public SurfacePlayer currPlayer;
    public boolean canListenStatusPush;
    public boolean isWaitingStart, isWaitingLogin;
    private boolean isReqExtraTask;
    private Button btnTop;
    private Marquee marquee;

    public MultiViewDialog(MainActivity activity, SurfacePlayer player, String deviceId) {
        super(activity);
        MultiViewDialog.instance = this;
        this.activity = activity;
        this.currPlayer = player;
        this.currDeviceId = deviceId;
        msgClientSocket = new WebSocketClient();
        msgClientSocket.addTextCallback(text -> {
            try {
                JSONObject json = new JSONObject(text);
                String cmd = json.getString("cmd");
                if (webSocketEvents.containsKey(cmd)) {
                    WebSocketMsg listener = webSocketEvents.get(cmd);
                    if (listener != null) {
                        log("消息返回，调用私有回调方法：" + cmd);
                        var data = json.getJSONObject("data");
                        listener.onRes(data, false);
                    }
                    webSocketEvents.remove(cmd);
                    //哪些协议在独立监听后就不走公共处理的
                    if ("extra_task_rsp".equals(cmd) || "get_status_rsp".equals(cmd)) {
                        return;
                    }
                }
                switch (cmd) {
                    case "waiting_account":
                        hideLoading();
                        switch2AccountPanel();
                        break;
                    case "waiting_captcha":
                        hideLoading();
                        switch2CaptchaPanel();
                        break;
                    case "extra_task_rsp":
                        List<Task> deviceExtraTasks = null;
                        if (!MainActivity.instance.deviceExtraTasks.containsKey(currDeviceId)) {
                            MainActivity.instance.deviceExtraTasks.put(currDeviceId, new ArrayList<>());
                        }
                        deviceExtraTasks = MainActivity.instance.deviceExtraTasks.get(currDeviceId);
                        JSONObject data = json.getJSONObject("data");
                        if (data.getInt("code") == 0) {
                            String extraTaskName = data.getString("task_name");
                            String extraTaskTime = data.getString("time");
                            Task extraTask = new Task(true, currTaskIndex + 1, 0, extraTaskName, extraTaskTime);
                            deviceExtraTasks.add(extraTask);
                            setMarquee(extraTaskName + Config.TaskDoingPrefix, false);
                            taskList.add(extraTask.index, extraTask);
                            //刷新索引
                            for (int i = 0; i < taskList.size(); i++) {
                                taskList.get(i).index = i;
                            }
                            if (tasksView.isVisible) {
                                if (isReqExtraTask) {
                                    tasksView.refreshUpdate();
                                }
                                tasksView.insertExtraTask(extraTask);
                            }
                        }
                        break;
                    case "get_status_rsp":
                        if (canListenStatusPush) {
                            data = json.getJSONObject("data");
                            if (data.getInt("code") == 0) {
                                int taskCmdId = data.getInt("task_id");
                                int status = data.getInt("status");
                                if (taskCmdId > 0) {
                                    //收到任务更新时，把数据拿去和请求的任务接口做处理
                                    int taskId = getTaskIdByCmdId(taskCmdId);
                                    onTaskUpdate(taskId, status);
                                }
                            }
                        }
                        break;
                }
            } catch (Exception e) {
                error(e.toString());
            }
        });
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.dialog);
        Window window = getWindow();
        if (window != null) {
            // 确保背景是透明的
            window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
            // 设置全屏
            window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        }

        GradientDrawable backgroundDrawable = (GradientDrawable) findViewById(R.id.dialog_bg).getBackground();
        if (currDeviceId.equals(Config.lockedDeviceId)) {
            backgroundDrawable.setStroke(15, Color.parseColor("#38CB6C"));
        } else {
            backgroundDrawable.setStroke(15, Color.parseColor("#666666"));
        }

        marquee = new Marquee(this);

        titleRightIcon = findViewById(R.id.title_right_icon);

        txtLogger = findViewById(R.id.txt_logger);
        Button btnDebug = findViewById(R.id.btn_debug);
        btnDebug.setOnClickListener(v -> {
            ViewGroup loggerLayer = findViewById(R.id.logger_layer);
            loggerLayer.setVisibility(loggerLayer.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE);
        });
        btnDebug.setVisibility(Config.IsDebugMode ? View.VISIBLE : View.GONE);

        //关闭按钮
        findViewById(R.id.btn_close).setOnClickListener(v -> close());
        btnTop = findViewById(R.id.btn_top);
        btnTop.setVisibility(View.VISIBLE);
        btnTop.setOnClickListener(v -> {
            if (tasksView.isVisible) {
                hideTasksPanel();
                btnTop.setText("查看全部体验任务");
            } else {
                showTasksPanel();
            }
        });
        btnTop.setScaleX(0);

        // 加载三个布局
        videoView = new VideoView(this);
        accountView = new AccountView(this);
        captchaView = new CaptchaView(this);
        tasksView = new TasksView(this);

        tasksView.hide();
        switch2VideoPanel();

        setMarquee("体验中...", false);
        startFlow();
    }

    private void startFlow() {
        String url = Config.APIBaseUrl + "/v1/ai/plan/" + currDeviceId;
        log("[reqCurrTasks]首次开始请求所有任务：" + url);
        HttpHelper.getAsync(url, res -> {
            try {
                log("[reqCurrTasks]请求所有任务返回：" + res);
                if (res != null) {
                    taskList.clear();
                    JSONObject json = new JSONObject(res);
                    if (json.getInt("code") == 200) {
                        JSONObject data = json.getJSONObject("data");
                        JSONObject myTask = data.getJSONObject("mytask");
                        log("我的任务：" + myTask);
                        alltask = data.getJSONArray("alltask");
                        currTaskIndex = myTask.getInt("task_index");
                        log("currTaskIndex:" + currTaskIndex);
                        String ids = json.getJSONObject("data").getJSONObject("planning").getString("task_ids");
                        String[] taskIds = ids.split(",");
                        for (int i = 0; i < taskIds.length; i++) {
                            int taskId = Integer.parseInt(taskIds[i]);
                            String taskName = "";
                            String taskTime = "";
                            for (int j = 0; j < alltask.length(); j++) {
                                JSONObject task = alltask.getJSONObject(j);
                                if (task.getInt("id") == taskId) {
                                    taskName = task.getString("name");
                                    taskTime = task.getString("icon");
                                    break;
                                }
                            }
                            taskList.add(new Task(false, i, taskId, taskName, taskTime));
                        }
                        log("显示顶部按钮");
                        showBtnTop();
                        log("连接Socket");
                        msgClientSocket.connect(Config.WSBaseUrl + "/device/c/" + currDeviceId, () -> {
                            try {
                                log("请求额外任务");
                                isReqExtraTask = true;
                                JSONObject params = new JSONObject();
                                params.put("cmd", "extra_task_req");
                                reqWebSocket(params, "extra_task_rsp", (JSONObject extraData, boolean isTimeout) -> {
                                    isReqExtraTask = false;
                                    if (isTimeout) {
                                        error("请求额外任务超时");
                                        popupMsg("请求额外任务超时", false, 2000);
                                    }
                                    try {
                                        if (!isTimeout && extraData.getInt("code") == 0) {
                                            if (MainActivity.instance.deviceExtraTasks.containsKey(currDeviceId)) {
                                                List<Task> extraTaskList = MainActivity.instance.deviceExtraTasks.get(currDeviceId);
                                                for (int i = 0; i < extraTaskList.size(); i++) {
                                                    Task task = extraTaskList.get(i);
                                                    log("插入额外任务：" + task.name);
                                                    taskList.add(task.index, task);
                                                }
                                            }
                                            log("刷新索引");
                                            for (int i = 0; i < taskList.size(); i++) {
                                                taskList.get(i).index = i;
                                            }
                                        }

                                        //超不超时都执行查询状态
                                        if (currDeviceId.equals(Config.lockedDeviceId)) {
                                            log("我的设备，请求是否需要启动app");
                                            JSONObject params2 = new JSONObject();
                                            params2.put("cmd", "get_status_req");
                                            reqWebSocket(params2, "get_status_rsp", (JSONObject statusData, boolean isStatusTimeout) -> {
                                                try {
                                                    if (!isStatusTimeout) {
                                                        if (statusData.getInt("task_id") < 0) {
                                                            log("任务Id小于等于0，说明未登录，触发start：" + currDeviceId);
                                                            setMarquee("正在启动目标app", true);
                                                            sendStartCmd();
                                                            return;
                                                        } else {
                                                            log("任务Id大于0，app已经启动：" + currDeviceId);
                                                        }
                                                    } else {
                                                        error("询问是否需要发start超时");
                                                    }
                                                    canListenStatusPush = true;
                                                    setMarquee(getCurrTaskName() + Config.TaskDoingPrefix, false);
                                                    tasksView.refreshUpdate();
                                                } catch (JSONException e) {
                                                    error(e.toString());
                                                    e.printStackTrace();
                                                }
                                            }, 5000);
                                        } else {
                                            log("非我的设备,无需登录，可以开始接收状态推送了");
                                            canListenStatusPush = true;
                                            setMarquee(getCurrTaskName() + Config.TaskDoingPrefix, false);
                                            tasksView.refreshUpdate();
                                        }
                                    } catch (JSONException e) {
                                        error(e.toString());
                                    }
                                }, 5000);
                            } catch (JSONException e) {
                                error(e.toString());
                            }
                        }, false);
                        return;
                    }
                }
            } catch (JSONException e) {
                error(e.toString());
            }
            log("设备无任务");
        });
    }

    private void showBtnTop() {
        btnTop.setScaleX(0.8f);
        ObjectAnimator scaleAnimator = ObjectAnimator.ofFloat(btnTop, "scaleX", 0f, 1f);
        scaleAnimator.setDuration(200);
        scaleAnimator.setInterpolator(AnimType.singleBounceInterpolator);
        scaleAnimator.start();
    }

    private void onTaskUpdate(int pushTaskId, int pushStatus) {
        String url = Config.APIBaseUrl + "/v1/ai/plan/" + currDeviceId;
        log("[reqCurrTasks]请求所有任务：" + url);
        HttpHelper.getAsync(url, res -> {
            try {
                log("[reqCurrTasks]请求所有任务返回：" + res);
                if (res != null) {
                    JSONObject json = new JSONObject(res);
                    if (json.getInt("code") != 200) {
                        error("[reqCurrTasks]请求计划组列表失败");
                        return;
                    }
                    JSONObject data = json.getJSONObject("data");
                    JSONObject myTask = data.getJSONObject("mytask");
                    currTaskIndex = myTask.getInt("task_index");
                    log("currTaskIndex:" + currTaskIndex);
                    currTaskComplated = pushStatus == 2;
                    String currTaskName = getCurrTaskName();
                    if (VideoView.class.getSimpleName().equals(currView)) {
                        boolean canSetMarquee = true;
                        if (currDeviceId.equals(Config.lockedDeviceId)) {
                            canSetMarquee = (!isWaitingStart && !isWaitingLogin);
                        }
                        if (canSetMarquee) {
                            if (pushStatus == 2) {
                                setMarquee(currTaskName + Config.TaskFinishSuffix, true);
                            } else {
                                setMarquee(Config.TaskStartPrefix + currTaskName, false);
                            }
                        }
                    }
                    if (pushStatus == 2) {
                        popupMsg(currTaskName + Config.TaskFinishSuffix, true, 3000);
                    } else {
                        popupMsg(Config.TaskStartPrefix + currTaskName, false, 3000);
                    }
                    tasksView.onTaskUpdate();
                } else {
                    popupMsg("读取任务列表失败", false, 2000);
                }
            } catch (JSONException e) {
                error(e.toString());
            }
        });
    }

    public void sendStartCmd() {
        if (isWaitingStart) return;
        hideLoading();
        try {
            JSONObject json = new JSONObject();
            json.put("cmd", "start_req");
            isWaitingStart = true;
            reqWebSocket(json, "start_rsp", (JSONObject data, boolean isTimeout) -> {
                if (!isTimeout) {
                    try {
                        if (data.getInt("code") == -1) {
                            log("收到code=-1，重新请求一次");
                            setMarquee(Config.TaskNotLogin, false);
                            sendStartCmd();
                        } else {
                            setMarquee("准备登录用户账号", false);
                        }
                    } catch (JSONException e) {
                        error(e.toString());
                    }
                }
                isWaitingStart = false;
            }, 0);
        } catch (JSONException e) {
            error(e.toString());
        }
    }

    public void reqWebSocket(JSONObject reqData, String rspCmd, WebSocketMsg callback, int timeout) {
        if (rspCmd != null && !rspCmd.isEmpty() && callback != null) {
            webSocketEvents.put(rspCmd, callback);
            if (timeout > 0) {
                handler.postDelayed(() -> {
                    if (webSocketEvents.containsKey(rspCmd)) {
                        webSocketEvents.get(rspCmd).onRes(null, true);
                        webSocketEvents.remove(rspCmd);
                    }
                }, timeout);
            }
        }
        msgClientSocket.sendMessage(reqData.toString());
    }

    public void switch2VideoPanel() {
        if (VideoView.class.getSimpleName().equals(currView)) {
            return;
        }
        GradientDrawable backgroundDrawable = (GradientDrawable) findViewById(R.id.dialog_bg).getBackground();
        backgroundDrawable.setColor(Color.parseColor("#000000"));
        videoView.show();
        accountView.hide();
        captchaView.hide();
        currView = VideoView.class.getSimpleName();
    }

    public void switch2AccountPanel() {
        if (AccountView.class.getSimpleName().equals(currView)) {
            return;
        }
        isWaitingLogin = true;
        hideLoading();
        setMarquee("正在登录账号", false);
        GradientDrawable backgroundDrawable = (GradientDrawable) findViewById(R.id.dialog_bg).getBackground();
        backgroundDrawable.setColor(Color.parseColor("#eeeeee"));
        videoView.hide();
        accountView.show();
        captchaView.hide();
        currView = AccountView.class.getSimpleName();
    }

    public void switch2CaptchaPanel() {
        if (CaptchaView.class.getSimpleName().equals(currView)) {
            return;
        }
        isWaitingLogin = true;
        hideLoading();
        setMarquee("正在登录账号", false);
        GradientDrawable backgroundDrawable = (GradientDrawable) findViewById(R.id.dialog_bg).getBackground();
        backgroundDrawable.setColor(Color.parseColor("#eeeeee"));
        videoView.hide();
        accountView.hide();
        captchaView.show();
        currView = CaptchaView.class.getSimpleName();
    }

    public void showTasksPanel() {
        GradientDrawable backgroundDrawable = (GradientDrawable) findViewById(R.id.dialog_bg).getBackground();
        backgroundDrawable.setColor(Color.parseColor("#eeeeee"));
        tasksView.show();
        tasksView.createItems(taskList);
    }

    public void hideTasksPanel() {
        tasksView.hide();
        if (VideoView.class.getSimpleName().equals(currView)) {
            GradientDrawable backgroundDrawable = (GradientDrawable) findViewById(R.id.dialog_bg).getBackground();
            backgroundDrawable.setColor(Color.parseColor("#000000"));
        }
    }

    public void onLoginSuccess() {
        isWaitingLogin = false;
        canListenStatusPush = true; //开始监听推送
        setMarquee("登录成功", true);
    }

    public void setMarquee(String title, boolean isComplated) {
        String tit = title.length() > 11 ? title.substring(0, 11) + "..." : title;
        marquee.setText(tit);
        if (isComplated) {
            titleRightIcon.setImageResource(R.drawable.finished);
            if (titleRightIconAnim != null) {
                titleRightIconAnim.cancel();
            }
            titleRightIcon.setRotation(0f);
        } else {
            titleRightIcon.setImageResource(R.drawable.doing);
            if (titleRightIconAnim == null) {
                titleRightIconAnim = ObjectAnimator.ofFloat(titleRightIcon, "rotation", 0f, 350f);
                titleRightIconAnim.setDuration(1000);
                titleRightIconAnim.setRepeatCount(ObjectAnimator.INFINITE);
                titleRightIconAnim.setRepeatMode(ObjectAnimator.RESTART);
                titleRightIconAnim.setInterpolator(new LinearInterpolator());
            }
            titleRightIconAnim.start();
        }
    }

    public void popupMsg(String msg, boolean showIcon, int duration) {
        if (findViewById(R.id.overlay_mask).getVisibility() == View.VISIBLE && findViewById(R.id.popup_dialog).getVisibility() == View.VISIBLE) {
            return;
        }

        FrameLayout overlayMask = findViewById(R.id.overlay_mask);
        overlayMask.setVisibility(View.VISIBLE);
        overlayMask.setClickable(false);
        overlayMask.setFocusable(false);
        FrameLayout black = findViewById(R.id.black);
        black.setBackgroundColor(Color.BLACK);
        black.setAlpha(0);
        black.animate().alpha(0.5f).setDuration(250).start();

        Button popupDialog = findViewById(R.id.popup_dialog);
        popupDialog.setScaleX(0);
        popupDialog.setScaleY(0);
        popupDialog.setVisibility(View.VISIBLE);
        popupDialog.setText(msg);
        if (showIcon) {
            popupDialog.setCompoundDrawablesWithIntrinsicBounds(R.drawable.finished, 0, 0, 0);
        } else {
            popupDialog.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
        }
        findViewById(R.id.loading).setVisibility(View.GONE);

        popupDialog.animate().scaleX(1f).scaleY(1).setDuration(250).setInterpolator(new OvershootInterpolator(1.5f)).start();

        handler.postDelayed(() -> hidePopupMsg(), duration);
    }

    public void showLoading() {
        FrameLayout overlayMask = findViewById(R.id.overlay_mask);
        overlayMask.setVisibility(View.VISIBLE);
        overlayMask.setClickable(true);
        overlayMask.setFocusable(true);
        findViewById(R.id.black).setBackgroundColor(Color.parseColor("#00000000"));
        findViewById(R.id.popup_dialog).setVisibility(View.GONE);
        findViewById(R.id.loading).setVisibility(View.VISIBLE);
        handler.postDelayed(() -> hideLoading(), Config.APITimeout);
    }

    public void hidePopupMsg() {
        if (findViewById(R.id.popup_dialog).getVisibility() != View.VISIBLE) {
            return;
        }
        findViewById(R.id.overlay_mask).setVisibility(View.GONE);
    }

    public void hideLoading() {
        if (findViewById(R.id.popup_dialog).getVisibility() == View.VISIBLE) {
            return;
        }
        findViewById(R.id.overlay_mask).setVisibility(View.GONE);
    }

    public void close() {
        dismiss();
    }

    @Override
    public void dismiss() {
        super.dismiss();
        videoView.hide();
        accountView.hide();
        captchaView.hide();
        tasksView.hide();
        MultiViewDialog.instance = null;
        msgClientSocket.disconnect();
        videoView.resumeSerface();
        activity.textureAdapter.startAllPlayers();
    }

    public String getCurrTaskName() {
        if (taskList.size() > currTaskIndex) {
            return taskList.get(currTaskIndex).name;
        }
        return null;
    }

    public int getTaskIdByCmdId(int cmdId) {
        if (alltask != null) {
            try {
                for (int i = 0; i < alltask.length(); i++) {
                    JSONObject task = alltask.getJSONObject(i);
                    if (task.getInt("cmd_id") == cmdId) {
                        return task.getInt("id");
                    }
                }
            } catch (JSONException e) {
                error(e.toString());
            }
        }
        return 0;
    }

    private void log(String msg) {
        Logger.log(msg, getClass(), false);
    }

    private void error(String msg) {
        Logger.error(msg, getClass(), false);
    }
}